﻿define([
    "dojo/_base/declare", "esri/InfoTemplate", "esri/layers/ArcGISDynamicMapServiceLayer",
    'esri/tasks/ClassBreaksDefinition',
    'esri/tasks/GenerateRendererParameters', "esri/tasks/AlgorithmicColorRamp",
    'esri/tasks/GenerateRendererTask', 'esri/tasks/UniqueValueDefinition', "esri/Color",
    "esri/layers/LayerDrawingOptions", "esri/layers/LabelClass"
], function(declare, InfoTemplate, ArcGISDynamicMapServiceLayer, ClassBreaksDefinition, GenerateRendererParameters, AlgorithmicColorRamp, GenerateRendererTask, UniqueValueDefinition, Color, LayerDrawingOptions, LabelClass) {
    var arcGISDynamicMapServiceLayer = declare([ArcGISDynamicMapServiceLayer], {

        constructor: function(options) {
            //this.inherited(arguments, [options]);

            this._map = null; //地图对象

        }

        ,
        _setMap: function(map, svg) {
            var me = this;
            var g = this.inherited(arguments);

            me._map = map;

            return g;
        }

        ,
        _unsetMap: function(map, svg) {
            var me = this;
            me.inherited(arguments);
            if (me._clickHandle) {
                me._clickHandle.remove()
                me._clickHandle = null;
            }
            if (map._dyClickHandleObj && map._dyClickHandleObj[me.id]) {
                delete map._dyClickHandleObj[me.id];
            };

            me._map = null;
        },
        setData: function(mapView, layer) {
            var me = this;
            if (!mapView) {
                return;
            };
            var mapUtils = mapView.mapUtils;
            if (!mapUtils) {
                return;
            };
            me._mapView = mapView;
            me._mapUtils = mapUtils;
            var map = mapView.getMap();
            if (!map) {
                return;
            }


            var options = layer.layer || {};
            me._options = options;

            var data = options.data || [];

            if (data && data.length > 0) {
                me.setVisibleLayers(data);
            };
            if (options.layerDefinitions && options.layerDefinitions.length > 0) {
                me.setLayerDefinitions(options.layerDefinitions)
            };

            if (typeof options.callback == 'function') {
                options.callback(layer);
            };
            if (options.infoTemplates) {
                var keys = Object.keys(options.infoTemplates);
                keys.map(function(key) {
                    var infoTemplate = new InfoTemplate();
                    var item = options.infoTemplates[key] || {};
                    var title = item.title;
                    var content = item.content;
                    if (title) {
                        infoTemplate.setTitle(title);
                    };
                    if (content) {
                        infoTemplate.setContent(content);
                    };

                    options.infoTemplates[key].infoTemplate = infoTemplate;
                });
                me.infoTemplateHandle = me.setInfoTemplates(options.infoTemplates);
                // mapUtils.changeOpenInfoWindowTitleButtonClass(mapView);
            };
            if (me._clickHandle && me._clickHandle.remove) {
                me._clickHandle.remove();
                me._clickHandle = null;
            };
            if (options.onClick) {
                me._clickHandle = map.on('click', function(e) {
                    if (me.visible) {
                        me.clickEvent.call(me, e);
                    };
                });
                map._dyClickHandleObj = map._dyClickHandleObj || {};
                map._dyClickEvtObj = map._dyClickEvtObj || {};
                map._dyClickHandleObj[me.id] = me._clickHandle;
            } else if (options.onMapClick) {
                me._clickHandle = map.on('click', function(e) {
                    if (me.visible) {
                        me.mapClickEvent.call(me, e);
                    };
                });
                map._dyClickHandleObj = map._dyClickHandleObj || {};
                map._dyClickEvtObj = map._dyClickEvtObj || {};
                map._dyClickHandleObj[me.id] = me._clickHandle;
            } else if (options.infoTemplates) {
                me._clickHandle = map.on('click', function(e) {
                    console.log(me)
                    mapUtils.changeOpenInfoWindowTitleButtonClass(mapView);
                });
            };

        },
        mapClickEvent: function(e) {
            var me = this;
            var map = me._map;
            if (!map) {
                return;
            };
            e.getLocation = function() {
                return me.getGraphicLocation(me._mapView, e);
            };
            e.mapView = me._mapView;
            me._options.onMapClick(e);
        },
        clickEvent: function(e) {
            var me = this;
            var map = me._map;
            if (!map) {
                return;
            };
            var _dyClickHandleKeys = Object.keys(map._dyClickHandleObj);
            var _dyClickHandleLen = _dyClickHandleKeys.length;
            if (me._options && me._options.onClick) {
                me._mapUtils._currentClickLayer = me.id;
                e.getLocation = function() {
                    return me.getGraphicLocation(me._mapView, e);
                };
                me._mapUtils.identifyTask(me._mapView, me._options.layerUrl, {
                    ...me._options,
                    geometry: me._mapUtils.createPoint(me._mapView, { x: e.mapPoint.x, y: e.mapPoint.y }),
                    layerIds: me._options.data,
                    callback: function(evt) {
                        if (!map._clickHandleCount) {
                            map._clickHandleCount = 1;
                        } else {
                            map._clickHandleCount++;
                        };

                        evt.mapView = me._mapView;

                        map._dyClickEvtObj[me.id] = evt;

                        if (map._clickHandleCount == _dyClickHandleLen) {
                            map._clickHandleCount = 0;
                            var _clickLayerNames = Object.keys(map._dyClickEvtObj);
                            for (let i = _clickLayerNames.length - 1; i >= 0; i--) {
                                var _layerName = _dyClickHandleKeys[i];
                                var e = map._dyClickEvtObj[_layerName];
                                if (e && e.features && e.features.length > 0) {
                                    var _layer = map.getLayer(_layerName);
                                    if (_layer && _layer.visible) {
                                        _layer._options.onClick(e);
                                        break;
                                    };
                                };
                            };
                            map._dyClickEvtObj = {};
                        }
                    },
                    ...me._options.identifyOptions
                });

            };
        },
        getGraphicLocation: function(mapView, esriEvent) {
            var geometry = esriEvent.mapPoint;
            var lngFieldName = mapView.getLngFieldName();
            var latFieldName = mapView.getLatFieldName();
            var location = {};
            location[lngFieldName] = geometry.x;
            location[latFieldName] = geometry.y;
            return location;
        },
        _createUniqueValueDefinition: function(info) {
            var classDef = new UniqueValueDefinition();
            classDef.attributeField = info.field;
            classDef.attributeField2 = info.field2;
            classDef.attributeField3 = info.field3;
            classDef.baseSymbol = info.symbol;
            classDef.type = 'uniqueValueDef';
            if (info.fromColor && info.toColor) {
                var colorRamp = new AlgorithmicColorRamp();
                colorRamp.fromColor = new Color.fromHex(info.fromColor);
                colorRamp.toColor = new Color.fromHex(info.toColor);
                colorRamp.algorithm = info.algorithm || "hsv";
                classDef.colorRamp = colorRamp;
            }

            return classDef;

        },
        _createClassBreaksDefinition: function(info) {
            var classDef = new ClassBreaksDefinition();
            classDef.classificationField = info.field;
            classDef.classificationMethod = info.classificationMethod || "natural-breaks";
            classDef.baseSymbol = info.symbol;
            classDef.type = 'classBreaksDef';
            classDef.breakCount = info.breakCount || 5;
            if (info.fromColor && info.toColor) {
                var colorRamp = new AlgorithmicColorRamp();
                colorRamp.fromColor = new Color.fromHex(info.fromColor);
                colorRamp.toColor = new Color.fromHex(info.toColor);
                colorRamp.algorithm = info.algorithm || "hsv";
                classDef.colorRamp = colorRamp;
            }

            return classDef;

        },
        _createDefinition: function(info) {
            var classDef = null;
            switch (info.type) {
                case this._mapView.mapUtils.Enum.RenderType.UniqueValueRenderer:
                    classDef = this._createUniqueValueDefinition(info);
                    break;
                case this._mapView.mapUtils.Enum.RenderType.ClassBreaksRenderer:
                    classDef = this._createClassBreaksDefinition(info);
                    break;
                default:
                    classDef = this._createUniqueValueDefinition(info);
                    break;
            }
            return classDef;
        },
        _generateRenderer: function(info, callback, errCallback) {
            var me = this;
            var url = me.url;
            var classDef = me._createDefinition(info);
            var params = new GenerateRendererParameters();
            params.classificationDefinition = classDef;
            var generateRenderer = new GenerateRendererTask(url + '/' + info.id);

            generateRenderer.execute(params, callback, errCallback);
        },
        setRenderers: function(options) {
            var me = this;
            options = { rendererLayerInfos: [{ id: '', field: '', classDefType: '', renderer: null }], ...options };
            var rendererLayerInfos = options.rendererLayerInfos;
            var optionsArray = [];
            for (let i = 0; i < rendererLayerInfos.length; i++) {

                me._generateRenderer(rendererLayerInfos[i], function(renderer) {
                    if (typeof rendererLayerInfos[i].renderer == 'function') {
                        rendererLayerInfos[i].renderer(renderer, _callback)
                    } else {
                        _callback();
                    }

                    function _callback() {
                        var drawingOptions = new LayerDrawingOptions();
                        drawingOptions.renderer = renderer;
                        // var lc = me._getLabelInfos(rendererLayerInfos[i].labelInfo);
                        // if (lc) {
                        //     drawingOptions.labelingInfo = lc;
                        // }
                        // ;
                        optionsArray[rendererLayerInfos[i].id] = drawingOptions;
                        if (i == rendererLayerInfos.length - 1) {
                            me.setLayerDrawingOptions(optionsArray);
                        };
                    }

                }, function(err) {
                    console.log("error: ", JSON.stringify(err));
                })
            };
        },
        _getLabelInfos: function(options) {
            var me = this;
            options = {
                id: '',
                symbol: null,
                json: null,
                ...options
            };
            var lc = null;
            if (options.json) {
                lc = new LabelClass(options.json);
                lc.symbol = options.symbol;

            }
            return lc;
        }
    });
    return arcGISDynamicMapServiceLayer;
});